---
description: |-
  Describes how to set up a standalone OpenBao with TLS certificate
---

# Standalone server with TLS

:::warning

**Important Note:** This chart is not compatible with Helm 2. Please use Helm 3.6+ with this chart.

:::


This example can be used to set up a single server OpenBao cluster using TLS.

1. Create key & certificate using Kubernetes CA
2. Store key & cert into [Kubernetes secrets store](https://kubernetes.io/docs/concepts/configuration/secret/)
3. Configure helm chart to use Kubernetes secret from step 2

## 1. create key & certificate using kubernetes CA

There are four variables that will be used in this example.

```bash
# SERVICE is the name of the OpenBao service in kubernetes.
# It does not have to match the actual running service, though it may help for consistency.
export SERVICE=openbao-server-tls

# NAMESPACE where the OpenBao service is running.
export NAMESPACE=openbao-namespace

# SECRET_NAME to create in the kubernetes secrets store.
export SECRET_NAME=openbao-server-tls

# TMPDIR is a temporary working directory.
export TMPDIR=/tmp

# CSR_NAME will be the name of our certificate signing request as seen by kubernetes.
export CSR_NAME=openbao-csr
```

1. Create a key for Kubernetes to sign.

   ```shell-session
   $ openssl genrsa -out ${TMPDIR}/openbao.key 2048
   Generating RSA private key, 2048 bit long modulus
...................................................................................................+++
...............+++
e is 65537 (0x10001)
   ```

2. Create a Certificate Signing Request (CSR).

   1. Create a file `${TMPDIR}/csr.conf` with the following contents:

      ```bash
      cat <<EOF >${TMPDIR}/csr.conf
      [req]
      req_extensions = v3_req
      distinguished_name = req_distinguished_name
      [req_distinguished_name]
      [ v3_req ]
      basicConstraints = CA:FALSE
      keyUsage = nonRepudiation, digitalSignature, keyEncipherment
      extendedKeyUsage = serverAuth
      subjectAltName = @alt_names
      [alt_names]
      DNS.1 = *.${SERVICE}
      DNS.2 = *.${SERVICE}.${NAMESPACE}
      DNS.3 = *.${SERVICE}.${NAMESPACE}.svc
      DNS.4 = *.${SERVICE}.${NAMESPACE}.svc.cluster.local
      IP.1 = 127.0.0.1
      EOF
      ```

   2. Create a CSR.

      ```bash
      openssl req -new \
                  -key ${TMPDIR}/openbao.key \
                  -subj "/CN=system:node:${SERVICE}.${NAMESPACE}.svc;/O=system:nodes" \
                  -out ${TMPDIR}/server.csr \
                  -config ${TMPDIR}/csr.conf
      ```

3. Create the certificate

:::warning

 **Important Note:** If you are using EKS, certificate signing requirements have changed.  As per the AWS [certificate signing](https://docs.aws.amazon.com/eks/latest/userguide/cert-signing.html) documentation, EKS version `1.22` and later now requires the `signerName` to be `beta.eks.amazonaws.com/app-serving`, otherwise, the CSR will be approved but the certificate will not be issued.

:::

   1. Create a file `${TMPDIR}/csr.yaml` with the following contents:

      ```bash
      cat <<EOF >${TMPDIR}/csr.yaml
      apiVersion: certificates.k8s.io/v1
      kind: CertificateSigningRequest
      metadata:
        name: ${CSR_NAME}
      spec:
        signerName: kubernetes.io/kubelet-serving
        groups:
        - system:authenticated
        request: $(base64 ${TMPDIR}/server.csr | tr -d '\n')
        signerName: kubernetes.io/kubelet-serving
        usages:
        - digital signature
        - key encipherment
        - server auth
      EOF
      ```

   2. Send the CSR to Kubernetes.

      ```shell-session
      $ kubectl create -f ${TMPDIR}/csr.yaml
      certificatesigningrequest.certificates.k8s.io/openbao-csr created
      ```

:::info

If this process is automated, you may need to wait to ensure the CSR has been received and stored:
      `kubectl get csr ${CSR_NAME}`

:::

   3. Approve the CSR in Kubernetes.

      ```shell-session
      $ kubectl certificate approve ${CSR_NAME}
      certificatesigningrequest.certificates.k8s.io/openbao-csr approved
      ```

   4. Verify that the certificate was approved and issued.
      ```shell-session
      $ kubectl get csr ${CSR_NAME}
      NAME        AGE     SIGNERNAME                                    REQUESTOR                        CONDITION
      openbao-csr   1m13s   kubernetes.io/kubelet-serving                 kubernetes-admin                 Approved,Issued
      ```

## 2. store key, cert, and kubernetes CA into kubernetes secrets store

1. Retrieve the certificate.

   ```shell-session
   $ serverCert=$(kubectl get csr ${CSR_NAME} -o jsonpath='{.status.certificate}')
   ```

:::info

If this process is automated, you may need to wait to ensure the certificate has been created.
   If it hasn't, this will return an empty string.

:::

2. Write the certificate out to a file.

   ```shell-session
   $ echo "${serverCert}" | openssl base64 -d -A -out ${TMPDIR}/openbao.crt
   ```

3. Retrieve Kubernetes CA.

   ```bash
   kubectl get secret \
     -o jsonpath="{.items[?(@.type==\"kubernetes.io/service-account-token\")].data['ca\.crt']}" \
     | base64 --decode > ${TMPDIR}/openbao.ca
   ```

4. Create the namespace.

    ```shell-session
    $ kubectl create namespace ${NAMESPACE}
    namespace/openbao-namespace created
    ```

5. Store the key, cert, and Kubernetes CA into Kubernetes secrets.

   ```shell-session
   $ kubectl create secret generic ${SECRET_NAME} \
       --namespace ${NAMESPACE} \
       --from-file=openbao.key=${TMPDIR}/openbao.key \
       --from-file=openbao.crt=${TMPDIR}/openbao.crt \
       --from-file=openbao.ca=${TMPDIR}/openbao.ca

   # secret/openbao-server-tls created
   ```

## 3. helm configuration

The below `custom-values.yaml` can be used to set up a single server OpenBao cluster using TLS.
This assumes that a Kubernetes `secret` exists with the server certificate, key and
certificate authority:

```yaml
global:
  enabled: true
  tlsDisable: false

server:
  extraEnvironmentVars:
    OPENBAO_CACERT: /openbao/userconfig/openbao-server-tls/openbao.ca

  volumes:
    - name: userconfig-openbao-server-tls
      secret:
        defaultMode: 420
        secretName: openbao-server-tls # Matches the ${SECRET_NAME} from above

  volumeMounts:
    - mountPath: /openbao/userconfig/openbao-server-tls
      name: userconfig-openbao-server-tls
      readOnly: true

  standalone:
    enabled: true
    config: |
      listener "tcp" {
        address = "[::]:8200"
        cluster_address = "[::]:8201"
        tls_cert_file = "/openbao/userconfig/openbao-server-tls/openbao.crt"
        tls_key_file  = "/openbao/userconfig/openbao-server-tls/openbao.key"
        tls_client_ca_file = "/openbao/userconfig/openbao-server-tls/openbao.ca"
      }

      storage "file" {
        path = "/openbao/data"
      }
```
